package task

import (
	"context"
	"encoding/json"
	"errors"
	"smart-flow/server/config"
	"smart-flow/server/executor"
	"smart-flow/server/logger"
	"smart-flow/server/net"
	"smart-flow/server/redis"
	"smart-flow/server/utils"
	"time"

	redisLib "github.com/go-redis/redis/v8"
	"go.uber.org/zap"
)

var (
	checkFinishedStartDuration = 30 * time.Second
)

func StartCheckFinishedAgent() {
	go checkFinishedAgent(config.IspCustom)
	time.Sleep(time.Second)
	go checkFinishedAgent(config.IspTelecom)
	time.Sleep(time.Second)
	go checkFinishedAgent(config.IspMobile)
	time.Sleep(time.Second)
	go checkFinishedAgent(config.IspUnicom)
}

func checkFinishedAgent(isp string) {
	time.Sleep(checkFinishedStartDuration)
	ticker := time.NewTicker(60 * time.Second)
	defer ticker.Stop()
	for range ticker.C {
		doCheckFinishedAgent(isp)
	}
}

func doCheckFinishedAgent(isp string) {
	var (
		nextCursor   uint64
		keys         []string
		err          error
		finishedUids []string
	)
	anyKey := utils.GenIspAnyKey(config.FlowManageKey, isp)
	now := time.Now().Unix()
	for {
		keys, nextCursor, err = redis.RDB.HScan(context.Background(), anyKey, nextCursor, "*", 1000).Result()
		if err != nil {
			if errors.Is(err, redisLib.Nil) {
				return
			}
			logger.Logger.Error("[任务] Checker操作Redis异常", zap.Error(err))
			return
		}
		var agentCtx net.AgentContext
		for i := 0; i < len(keys); i += 2 {
			_ = json.Unmarshal([]byte(keys[i+1]), &agentCtx)
			if agentCtx.Duration > 0 && agentCtx.StartTime+int64(agentCtx.Duration*60+300) < now {
				finishedUids = append(finishedUids, agentCtx.Uid)
				executor.ExecutingInstance(isp).DelExecutor(agentCtx.Uid)
			}
		}
		if nextCursor == 0 {
			break
		}
	}
	for i := 0; i < len(finishedUids); i += 50 {
		redis.RDB.HDel(context.Background(), anyKey, finishedUids[i:min(len(finishedUids), i+50)]...)
	}
}
